﻿using Engine;
using Engine.Graphics;

namespace CommandBlock
{
    /// <summary>
    /// 自定义闪电粒子
    /// </summary>
    public class LightningStrikeParticleSystem : ParticleSystem<LightningStrikeParticleSystem.Particle>
    {
        public class Particle : Game.Particle
        {
            public float TimeToLive;
            public Color ShowColor;
        }

        public PrimitivesRenderer3D m_primitivesRenderer3D = new PrimitivesRenderer3D();

        public Random m_random = new Random();

        public LightningStrikeParticleSystem(Vector3 position, Color color)
            : base(1)
        {
            Particle obj = base.Particles[0];
            obj.IsActive = true;
            obj.Position = position;
            obj.TimeToLive = 1f;
            obj.ShowColor = color;
        }

        public override bool Simulate(float dt)
        {
            dt = MathUtils.Clamp(dt, 0f, 0.1f);
            bool flag = false;
            for (int i = 0; i < base.Particles.Length; i++)
            {
                Particle particle = base.Particles[i];
                if (particle.IsActive)
                {
                    flag = true;
                    particle.TimeToLive -= dt;
                    if (particle.TimeToLive <= 0f)
                    {
                        particle.IsActive = false;
                    }
                }
            }
            return !flag;
        }

        public override void Draw(Camera camera)
        {
            FlatBatch3D flatBatch3D = m_primitivesRenderer3D.FlatBatch(0, DepthStencilState.DepthRead, null, BlendState.Additive);
            Vector3 unitY = Vector3.UnitY;
            Vector3 v = Vector3.Normalize(Vector3.Cross(camera.ViewDirection, unitY));
            Viewport viewport = Display.Viewport;
            for (int c = 0; c < base.Particles.Length; c++)
            {
                Particle particle = base.Particles[c];
                if (particle.IsActive)
                {
                    Vector3 value = particle.Position;
                    float num = Vector4.Transform(new Vector4(value, 1f), camera.ViewProjectionMatrix).W * 2f / ((float)viewport.Width * camera.ProjectionMatrix.M11);
                    for (int i = 0; i < (int)(particle.TimeToLive * 30f); i++)
                    {
                        float s = m_random.NormalFloat(0f, 1f * num);
                        float s2 = m_random.NormalFloat(0f, 1f * num);
                        Vector3 v2 = s * v + s2 * unitY;
                        float num2 = 260f;
                        while (num2 > value.Y)
                        {
                            uint num3 = MathUtils.Hash((uint)(particle.Position.X + 100f * particle.Position.Z + 200f * num2));
                            float num4 = MathUtils.Lerp(4f, 10f, (float)(double)(num3 & 0xFF) / 255f);
                            float s3 = ((num3 & 1) == 0) ? 1 : (-1);
                            float s4 = MathUtils.Lerp(0.05f, 0.2f, (float)(double)((num3 >> 8) & 0xFF) / 255f);
                            float num5 = num2;
                            float num6 = num5 - num4 * MathUtils.Lerp(0.45f, 0.55f, (float)(double)((num3 >> 16) & 0xFF) / 255f);
                            float num7 = num5 - num4 * MathUtils.Lerp(0.45f, 0.55f, (float)(double)((num3 >> 24) & 0xFF) / 255f);
                            float num8 = num5 - num4;
                            Vector3 p = new Vector3(value.X, num5, value.Z) + v2;
                            Vector3 vector = new Vector3(value.X, num6, value.Z) + v2 - num4 * v * s3 * s4;
                            Vector3 vector2 = new Vector3(value.X, num7, value.Z) + v2 + num4 * v * s3 * s4;
                            Vector3 p2 = new Vector3(value.X, num8, value.Z) + v2;
                            Color color = particle.ShowColor;
                            flatBatch3D.QueueLine(p, vector, color, color);
                            flatBatch3D.QueueLine(vector, vector2, color, color);
                            flatBatch3D.QueueLine(vector2, p2, color, color);
                            num2 -= num4;
                        }
                    }
                }
            }
            m_primitivesRenderer3D.Flush(camera.ViewProjectionMatrix);
        }
    }
}